package com.xtedu.examproject.util;

import com.xtedu.examproject.entity.UploadedFile;
import com.xtedu.examproject.service.UploadedFileService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.*;
import java.net.URLEncoder;
import java.util.List;

import static com.xtedu.examproject.util.UploadUtil.getFileExtension;

public class DownloadUtil {
    /**
     * 文件下载功能
     */
    public static void downloadFile(HttpServletRequest req, HttpServletResponse resp) {
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            // 设置字符编码
            req.setCharacterEncoding("UTF-8");
            resp.setCharacterEncoding("UTF-8");

            // 获取文件ID或考试ID
            String fileIdStr = req.getParameter("fileId");
            String examIdStr = req.getParameter("examId");

            UploadedFile uploadedFile = null;

            // 根据文件ID或考试ID查找文件
         if (examIdStr != null && !examIdStr.trim().isEmpty()) {
                int examId = Integer.parseInt(examIdStr);
                List<UploadedFile> files = UploadedFileService.findUrlByExamId(examId);
                if (files != null && !files.isEmpty()) {
                    // 获取最新的文件（与你的逻辑一致）
                    uploadedFile = files.get(files.size() - 1);
                }
            }

            // 检查文件是否存在
            if (uploadedFile == null) {
                sendErrorResponse(resp, "未找到相关文件");
                return;
            }

            // 检查物理文件是否存在
            File file = new File(uploadedFile.getUploadPath());
            if (!file.exists() || !file.isFile()) {
                sendErrorResponse(resp, "文件不存在或已被删除: " + uploadedFile.getOriginalName());
                return;
            }

            if (!file.canRead()) {
                sendErrorResponse(resp, "文件无法读取: " + uploadedFile.getOriginalName());
                return;
            }

            // 设置下载响应头
            setupDownloadHeaders(resp, uploadedFile.getOriginalName(), file.length(), uploadedFile.getContentType());

            // 传输文件内容
            inputStream = new FileInputStream(file);
            outputStream = resp.getOutputStream();

            byte[] buffer = new byte[8192]; // 8KB缓冲区
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();

            // 记录下载日志（可选）
            logDownloadActivity(uploadedFile, req);

        } catch (NumberFormatException e) {
            sendErrorResponse(resp, "参数格式错误");
        } catch (FileNotFoundException e) {
            sendErrorResponse(resp, "文件不存在");
        } catch (IOException e) {
            // 如果响应已经开始，无法发送错误信息，只能记录日志
            System.err.println("文件下载IO错误: " + e.getMessage());
        } catch (Exception e) {
            sendErrorResponse(resp, "下载失败: " + e.getMessage());
        } finally {
            // 关闭资源
            closeQuietly(inputStream);
            closeQuietly(outputStream);
        }
    }

    /**
     * 设置下载响应头
     */
    private static void setupDownloadHeaders(HttpServletResponse resp, String fileName,
                                             long fileSize, String contentType) throws IOException {
        // 重置响应
        resp.reset();

        // 设置内容类型
        if (contentType == null || contentType.isEmpty()) {
            contentType = determineContentType(fileName);
        }
        resp.setContentType(contentType);

        // 设置下载头信息，处理中文文件名
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8")
                .replaceAll("\\+", "%20"); // 处理空格

        resp.setHeader("Content-Disposition",
                "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);

        // 设置文件大小
        resp.setHeader("Content-Length", String.valueOf(fileSize));

        // 禁用缓存
        resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        resp.setHeader("Pragma", "no-cache");
        resp.setDateHeader("Expires", 0);
    }

    /**
     * 根据文件名确定内容类型
     */
    private static String determineContentType(String fileName) {
        String extension = getFileExtension(fileName).toLowerCase();
        switch (extension) {
            case "pdf": return "application/pdf";
            case "doc": return "application/msword";
            case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls": return "application/vnd.ms-excel";
            case "xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "csv": return "text/csv";
            case "txt": return "text/plain";
            case "jpg": case "jpeg": return "image/jpeg";
            case "png": return "image/png";
            case "zip": return "application/zip";
            case "rar": return "application/x-rar-compressed";
            default: return "application/octet-stream";
        }
    }

    /**
     * 发送错误响应
     */
    private static void sendErrorResponse(HttpServletResponse resp, String errorMessage) {
        try {
            if (!resp.isCommitted()) {
                resp.setContentType("application/json;charset=UTF-8");
                resp.getWriter().write("{\"success\":false,\"message\":\"" + errorMessage + "\"}");
            }
        } catch (IOException e) {
            System.err.println("发送错误响应失败: " + e.getMessage());
        }
    }

    /**
     * 记录下载活动（可选）
     */
    private static void logDownloadActivity(UploadedFile file, HttpServletRequest req) {
        // 这里可以记录下载日志，比如下载时间、下载者IP等
        String clientIP = req.getRemoteAddr();
        String userAgent = req.getHeader("User-Agent");

        System.out.println("文件下载记录: " + file.getOriginalName() +
                " | 下载者IP: " + clientIP +
                " | 时间: " + new java.util.Date());
    }

    /**
     * 安静关闭资源
     */
    private static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                // 忽略关闭异常
            }
        }
    }
}
